package utils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cern.colt.matrix.DoubleFactory1D;
import cern.colt.matrix.DoubleFactory2D;
import cern.colt.matrix.DoubleMatrix1D;
import cern.colt.matrix.DoubleMatrix2D;

public class DataInput {

	public static int getNumLines(String fileName) throws IOException{
		int numLines = 0;
		LineNumberReader in = new LineNumberReader(new FileReader(fileName));   
		while(in.readLine()!=null) numLines++;
		in.close();
		return numLines;
	}
	
	public static DoubleMatrix1D parseLibSVM(String lineWithoutLabel, int numFeatures){
		String[] items = lineWithoutLabel.split(" ");
		DoubleMatrix1D vector = DoubleFactory1D.sparse.make(numFeatures);
		for(String item : items){
			String[] fv = item.split(":");
			vector.setQuick(Integer.parseInt(fv[0])-1, Double.parseDouble(fv[1]));
		}
		return vector;
	}

	public static DoubleMatrix1D parseDense(String lineWithoutLabel, int numFeatures){
		String[] items = lineWithoutLabel.split(" ");
		DoubleMatrix1D vector = DoubleFactory1D.dense.make(numFeatures);
		for(int i=0;i<items.length;i++) vector.setQuick(i, Double.parseDouble(items[i]));
		return vector;
	}
	
	public static DoubleMatrix2D readLibSVM(String fileName, int numFeatures, List<Integer> labels) throws IOException{
		DoubleMatrix2D data = DoubleFactory2D.sparse.make(getNumLines(fileName), numFeatures);
		BufferedReader input = new BufferedReader(new FileReader(fileName));
		String line = null;
		int instanceID = 0;
		while((line=input.readLine())!=null){
			String[] items = line.split(" ");
			//label
			labels.add(Integer.parseInt(items[0]));
			//target
			for(int i=1;i<items.length;i++) {
				String[] fv = items[i].split(":");
				data.setQuick(instanceID, Integer.parseInt(fv[0])-1, Double.parseDouble(fv[1]));
			}
			instanceID ++;
		}
		input.close();
		return data;
	}

	public static DoubleMatrix2D readHLibSVM(String fileName, int numFeatures, List<String> labels) throws IOException{
		DoubleMatrix2D data = DoubleFactory2D.sparse.make(getNumLines(fileName), numFeatures);
		BufferedReader input = new BufferedReader(new FileReader(fileName));
		String line = null;
		int instanceID = 0;
		while((line=input.readLine())!=null){
			String[] items = line.split(" ");
			//label
			labels.add(items[0]);
			//target
			for(int i=1;i<items.length;i++) {
				String[] fv = items[i].split(":");
				data.setQuick(instanceID, Integer.parseInt(fv[0])-1, Double.parseDouble(fv[1]));
			}
			instanceID ++;
		}
		input.close();
		return data;
	}
	
	public static DoubleMatrix2D readDenseMatrix(String fileName, int numFeatures, List<Integer> labels) throws IOException {
		DoubleMatrix2D data = DoubleFactory2D.dense.make(getNumLines(fileName), numFeatures);
		BufferedReader input = new BufferedReader(new FileReader(fileName));
		String line = null;
		int instanceID = 0;
		while((line=input.readLine())!=null){
			String[] items = line.split(" ");
			//target
			for(int i=1;i<items.length;i++) data.setQuick(instanceID, i, Double.parseDouble(items[i]));
			//label
			labels.add(Integer.parseInt(items[0]));
			instanceID ++;
		}
		input.close();		
		return data;
	}

	public static DoubleMatrix2D readHDenseMatrix(String fileName, int numFeatures, List<String> labels) throws IOException {
		DoubleMatrix2D data = DoubleFactory2D.dense.make(getNumLines(fileName), numFeatures);
		BufferedReader input = new BufferedReader(new FileReader(fileName));
		String line = null;
		int instanceID = 0;
		while((line=input.readLine())!=null){
			String[] items = line.split(" ");
			//target
			for(int i=1;i<items.length;i++) data.setQuick(instanceID, i, Double.parseDouble(items[i]));
			//label
			labels.add(items[0]);
			instanceID ++;
		}
		input.close();		
		return data;
	}
	
	public static DoubleMatrix2D readLinkTable(String fileName, int numUsers, List<Integer> idList) throws NumberFormatException, IOException {
		DoubleMatrix2D data = DoubleFactory2D.sparse.make(getNumLines(fileName), numUsers);
		BufferedReader input = new BufferedReader(new FileReader(fileName));
		String line = null;
		int instanceID = 0;
		while((line=input.readLine())!=null){
			String[] items = line.split(" ");
			//target
			for(int i=1;i<items.length;i++) data.setQuick(instanceID, Integer.parseInt(items[i]), 1.0);
			//source
			idList.add(Integer.parseInt(items[0]));
			instanceID ++;
		}
		input.close();		
		return data;		
	}
	
	public static DoubleMatrix2D readPairList(String fileName, int numUsers, List<Integer> idList) throws NumberFormatException, IOException {
		BufferedReader input = new BufferedReader(new FileReader(fileName));
		String line = null;
		Map<Integer, Integer> idSet = new HashMap<Integer, Integer>();
		int instanceID = 0;
		while((line=input.readLine())!=null){
			int s = Integer.parseInt(line.split(" ")[0]);
			if(idSet.containsKey(s)) continue;
			else {
				idSet.put(s, instanceID); idList.add(s);
				instanceID ++;
			}
		}
		input.close();
		DoubleMatrix2D data = DoubleFactory2D.sparse.make(idSet.size(), numUsers);
		input = new BufferedReader(new FileReader(fileName));
		while((line=input.readLine())!=null){
			String[] items = line.split(" ");
			int s = Integer.parseInt(items[0]);
			int t = Integer.parseInt(items[1]);
			data.setQuick(idSet.get(s), t, 1.0);
		}
		input.close();		
		return data;		
	}
}
